#include "p_parser_expr.h"

// -----------------------------------------------------------------------------

bool is_value_expression_operation(const p_token_type &token_type)
{
   switch (token_type)
   {
   case TOK_AND:
   case TOK_NAND:
   case TOK_OR:
   case TOK_NOR:
   case TOK_XOR:
      return true;
   default:
      return false;
   }
   return false;
}

// -----------------------------------------------------------------------------

bool is_value_expression_term_operation(const p_token_type &token_type)
{
   switch (token_type)
   {
   case TOK_ADD:
   case TOK_SUB:
      return true;
   default:
      return false;
   }
   return false;
}

// -----------------------------------------------------------------------------

bool is_value_expression_term2_operation(const p_token_type &token_type)
{
   switch (token_type)
   {
   case TOK_MUL:
   case TOK_DIV:
      return true;
   default:
      return false;
   }
   return false;
}

// -----------------------------------------------------------------------------

bool is_value_expression_term3_operation(const p_token_type &token_type)
{
   switch (token_type)
   {
   case TOK_POWER:
      return true;
   default:
      return false;
   }
   return false;
}

// -----------------------------------------------------------------------------

bool is_value_bool_term_operation(const p_token_type &token_type)
{
   switch (token_type)
   {
   case TOK_LT:
   case TOK_LE:
   case TOK_GT:
   case TOK_GE:
   case TOK_NE:
   case TOK_EQ:
      return true;
   default:
      return false;
   }
   return false;
}

// -----------------------------------------------------------------------------

void parser_parse_value_expression_factor(p_parser_struct_ptr parser)
{
   // this is a rather complex operation here...
   const p_token_struct& curr_tok = next_token(parser);

   switch (curr_tok.type)
   {
   case TOK_IDENT:
      // just consuming for now...
      break;
   case TOK_EXCLAMATION_MARK:
      // now we have a type cast

      // the first element is a type expression...
      parser_parse_type_expression(parser, false);

      // ... and then we have a top level expression...
      parser_parse_value_expression_factor(parser);
      break;
   case TOK_ADDR:
      // this is the address operator...
      parser_parse_value_expression_factor(parser);
      break;
   default:
      break;
   }
}

// -----------------------------------------------------------------------------

/**
 * This function parses the array index/access.
 *
 * @param parser This is the parser object.
 */
void parser_parse_value_expression_array(p_parser_struct_ptr parser)
{
   // the top level expression...
   parser_parse_value_expression_factor(parser);

   while (test_token(parser).type == TOK_EBRO) {
      // consuming the token...
      next_token(parser);

      // well now we have an expression to parse...
      parser_parse_value_expression(parser);

      //
      const p_token_struct& curr_tok = next_token(parser);
      if (curr_tok.type != TOK_EBRC) {
         throw error_struct_create(
                                   "']' expected but '" + curr_tok.ident
                                            + "' found");
      }
   }
}

// -----------------------------------------------------------------------------

void parser_parse_value_expression_term3(p_parser_struct_ptr parser)
{
   // an expression is such as: and, or, xor, nand, nor
   parser_parse_value_expression_array(parser);

   while (is_value_expression_term3_operation(test_token(parser).type)) {
      // just consuming the token...
      next_token(parser);

      parser_parse_value_expression_array(parser);
   }
}

// -----------------------------------------------------------------------------

void parser_parse_value_expression_term2(p_parser_struct_ptr parser)
{
   // an expression is such as: and, or, xor, nand, nor
   parser_parse_value_expression_term3(parser);

   while (is_value_expression_term2_operation(test_token(parser).type)) {
      // just consuming the token...
      next_token(parser);

      parser_parse_value_expression_term3(parser);
   }
}

// -----------------------------------------------------------------------------

void parser_parse_value_expression_term(p_parser_struct_ptr parser)
{
   // an expression is such as: and, or, xor, nand, nor
   parser_parse_value_expression_term2(parser);

   while (is_value_expression_term_operation(test_token(parser).type)) {
      // just consuming the token...
      next_token(parser);

      parser_parse_value_expression_term2(parser);
   }
}

// -----------------------------------------------------------------------------

void parser_parse_value_bool_term(p_parser_struct_ptr parser)
{
   // an expression is such as: and, or, xor, nand, nor
   parser_parse_value_expression_term(parser);

   while (is_value_bool_term_operation(test_token(parser).type)) {
      // just consuming the token...
      next_token(parser);

      parser_parse_value_expression_term(parser);
   }
}

// -----------------------------------------------------------------------------

void parser_parse_value_expression(p_parser_struct_ptr parser)
{
   // an expression is such as: and, or, xor, nand, nor
   parser_parse_value_bool_term(parser);

   while (is_value_expression_operation(test_token(parser).type)) {
      // just consuming the token...
      next_token(parser);

      parser_parse_value_bool_term(parser);
   }
}

// -----------------------------------------------------------------------------
